package com.cvpoc.service.impl;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.StringReader;
import java.net.URL;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathExpressionException;
import javax.xml.xpath.XPathFactory;

import org.apache.solr.client.solrj.SolrQuery;
import org.apache.solr.client.solrj.SolrServer;
import org.apache.solr.client.solrj.SolrServerException;
import org.apache.solr.client.solrj.impl.CommonsHttpSolrServer;
import org.apache.solr.client.solrj.impl.XMLResponseParser;
import org.apache.solr.client.solrj.response.QueryResponse;
import org.apache.solr.common.SolrDocumentList;
import org.xml.sax.InputSource;

import com.cvpoc.exception.BusinessException;
import com.cvpoc.service.SolrService;

public class SolrServiceImpl implements SolrService {
	
	// container
	private URL url;
	// conversion de la réponse
	private InputStream response;
	// url de solar
	private String solrurlpath;
	// renvoi du status
	private boolean solrEnabled = false;

	public boolean isSolrEnabled() {
		return solrEnabled;
	}

	public void setSolrEnabled(boolean solrEnabled) {
		this.solrEnabled = solrEnabled;
	}

	/**
	 * 
	 * @param solrurlpath
	 * 
	 */
	public void setSolrurlpath(String solrurlpath) {
		this.solrurlpath = solrurlpath;
	}
	
	/**
	 * 
	 * @return
	 * @throws BusinessException
	 * @throws SolrServerException
	 * @throws IOException
	 * 
	 */
	
	public SolrServer solrServer() throws BusinessException, SolrServerException, IOException {
		CommonsHttpSolrServer server = new CommonsHttpSolrServer(solrurlpath);
		server.setSoTimeout(1000);  				// socket read timeout
		server.setConnectionTimeout(100);
		server.setDefaultMaxConnectionsPerHost(100);
		server.setMaxTotalConnections(100);
		server.setFollowRedirects(false);  			// defaults to false
		server.setMaxRetries(1); 					// defaults to 0.  > 1 not recommended.
		server.setParser(new XMLResponseParser()); 	// binary parser is used by default
		if(server.ping() != null) {
			setSolrEnabled(true);
		}
		return server;
	}
	
	/**
	 * 
	 * @param solrServer
	 * @param solrQuery
	 * @return
	 * @throws BusinessException
	 * @throws SolrServerException
	 * 
	 */
	
	public SolrDocumentList SolrServerDocuments(SolrServer solrServer, SolrQuery solrQuery) throws BusinessException, SolrServerException {
        QueryResponse response 		= solrServer.query(solrQuery);
        SolrDocumentList documents 	= response.getResults();
		return documents;
	}
	
	
	/**
	 * 
	 * Cette méthode fait une mise à jour complete des index de solr.
	 * 
	 * Chaque foix que cette méthode est éxécuté et que le parametre est à true, l'index de solr est nettoyé.
	 * 
	 * DataImportHandler : DIH
	 * 
	 * @throws BusinessException
	 * @throws IOException
	 * 
	 */
	public void solrServerFullImportRequest(boolean clean) throws BusinessException, IOException {
		//Reindexation suite à l'injection de donnée en base
		// seulement consulter les dernieres mises à jour, vérifier : http://localhost:8080/solr/dataimport
		if(isSolrEnabled() == true) {
			String command = "/dataimport?command=full-import";
			if(clean == false) {
				command += "&clean=false";
			}
			url = new URL(solrurlpath + command);
			response = url.openStream();	
		}
	}
	
	/**
	 * 
	 * Cette méthode ne met à jour que les données qui ont été modifiés depuis le dernier appel au niveau
	 * de l'indexation de solr. Il n'y a pas de suppression de l'index
	 * 
	 * Il faut donc envisager de lancer cette tâche que apres une période défniti
	 * 
	 * DataImportHandler : DIH
	 * 
	 * @throws BusinessException
	 * @throws IOException
	 * 
	 */
	
	public void solrServerDeltaImportRequest() throws BusinessException, IOException {
		if(isSolrEnabled() == true) {
			url = new URL(solrurlpath + "/dataimport?command=delta-import&clean=false&commit=true");
			response = url.openStream();	
		}
	}	
	
	/**
	 * 
	 * @param is
	 * @param expression
	 * @return
	 * @throws BusinessException
	 * @throws XPathExpressionException
	 * 
	 */
	
    public String solrXpathRequest(InputSource is, String expression) throws BusinessException, XPathExpressionException {
        XPath xpath = XPathFactory.newInstance().newXPath();
        String xpathExpression = expression;
        String result = xpath.evaluate(xpathExpression, is); 
        return result;
    }
    
	/**
	 * 
	 * @param query
	 * @return
	 * @throws BusinessException
	 * @throws IOException
	 * 
	 */
    
    public String solrQueryRequest(String query) throws BusinessException, IOException {
		url = new URL(solrurlpath + "/select/?q=" + query);
		response = url.openStream();
		BufferedReader reader = new BufferedReader(new InputStreamReader(response));
		String xmldata = "";
		for (String line; (line = reader.readLine()) != null;) {
			xmldata = xmldata + line;
		}
		reader.close();
		return xmldata;
    }
    
	/**
	 * 
	 * @param xmldata
	 * @return
	 * @throws BusinessException
	 * @throws ParserConfigurationException
	 * 
	 */
    
    public InputSource solrDocumentsRequest(String xmldata) throws BusinessException, ParserConfigurationException {
		DocumentBuilderFactory factory 	= DocumentBuilderFactory.newInstance();
	    DocumentBuilder builder 		= factory.newDocumentBuilder();
	    InputSource is 					= new InputSource(new StringReader(xmldata));
		return is;
    }
}
